变量提升:变量的声明写在可以在使用变量之后;
函数提升:函数可以先调用,后声明;
上面先解释了下我理解的这两个概念的定义。要真正理解它们,最好从变量对象的角度出发。引出变量对象的概念,要先理解执行上下文,也就是当控制器执行到可执行代码的时候,就会生成一个执行上下文,也就是代码的执行环境,会产生一个作用域。这个执行上下文的生命周期有两个阶段:创建阶段 和 代码执行阶段
创建阶段就会创建变量对象,创建的过程分三步:
1.建立arguments对象。检查当前上下文中的参数,建立该对象下的属性与属性值
2.先检查有没有函数声明(利用function关键字声明的函数,在变量对象中用函数名作为属性名,属性值是函数内存地址
的引用。如果函数名的引用已经存在,那么会被新的引用覆盖)
3.再检查变量声明,每找到一个变量声明,就在变量对象里用变量名作为属性名,属性值是undefined。如果变量名已经存在,直接跳过,目的是防止把同名的函数被修改成undefined
执行阶段会将变量对象转换为活动对象:
创建完成之后,就会开始执行代码,这个时候,会完成变量赋值,函数引用,以及执行其他代码。
(在变量对象创建过程中,其中的属性不可访问。只有在执行阶段转为活动对象后,才可以访问其中的内容)
先来一个简单的例子:
function foo(){
a = 2;
function a(){
console.log("函数")
}
console.log(a); //2
var a;
};
foo();
这个例子中,当控制器遇到这段代码时候,会形成一个执行上下文。随后进入到执行上下文的第一个生命周期:创建阶段,此时,执行创建变量对象的三个步骤。
- 由于没有参数。直接进入第二步。
- 首先检查上下文中有没有function关键字声明的函数,以a为属性名,函数的引用为属性值,添加到变量对象中。
- 再检查函数声明,发现了变量名a,但是,以a为属性名的属性值已经存在,所以跳过。
接下来进入第二个生命周期:代码执行
a被赋值为2,函数a未被调用。打印a等于2
函数提升也是一个道理,由于变量对象创建过程中会先检查function关键字声明的函数,以该函数的函数名为属性,值为函数地址的引用,添加进变量对象中。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。